﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using RegExStudio.RegExStudioEventArgs;

namespace RegExStudio.Forms
{
    public partial class FormMain : FormBase
    {
        /// <summary>
        /// Zählt mit wie viele RegEx schon erzeugt wurden
        /// Der Zähler wird beim Erstellen eines neuen Namens hinten dran gehängt
        /// </summary>
        private uint _regExCount = 1;

        /// <summary>
        /// Die RegEx Sammlung die bearbeitet wird
        /// </summary>
        private Xml.RegExSet _regExSet = null;

        /// <summary>
        /// Mapping ds anzeigt auf welchem TabControl sich eine RegEx befindet
        /// </summary>
        private Dictionary<Xml.RegExSetRegEx, CustomControls.CtrlRegExTab> _regExMapping = new Dictionary<Xml.RegExSetRegEx, CustomControls.CtrlRegExTab>();

        /// <summary>
        /// Mapping das anzeigt welche RegEx sich auf einem Tab befindet
        /// </summary>
        private Dictionary<CustomControls.CtrlRegExTab, Xml.RegExSetRegEx> _controlMapping = new Dictionary<CustomControls.CtrlRegExTab, Xml.RegExSetRegEx>();

        /// <summary>
        /// Merker und Anzeiger ob die Datei schon bearbeitet wurde
        /// </summary>
        private bool FileIsDirty
        {
            get { return lblFileIsDirty.Visible; }
            set { lblFileIsDirty.Visible = value; }
        }

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="regExSet"></param>
        public FormMain(Xml.RegExSet regExSet)
        {
            InitializeComponent();
            _regExSet = regExSet;
        }

        /// <summary>
        /// Das Formular wird erstmalig geladen
        /// Zeige die geladene RegEx an
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormMain_Load(object sender, EventArgs e)
        {
            ShowRegExSet();
            FileIsDirty = false;
        }

        /// <summary>
        /// Fügt ein neues Tab für eine RegEx hinzu
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuFileAddToolStripMenuItem_Click(object sender, EventArgs e)
        {
            NewRegEx();
            FileIsDirty = true;
        }

        /// <summary>
        /// Schliesst das aktuelle Tab und entfernt die RegEx aus dem RegExSet
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuFileCloseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CustomControls.CtrlRegExTab tab = tcRegExCollection.SelectedTab as CustomControls.CtrlRegExTab;

            CloseTab(tab);
            FileIsDirty = true;
        }

        /// <summary>
        /// Es wird eine neues RegExSet angelegt
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuFileNewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (FileIsDirty)
            {
                DialogResult rc = MessageBox.Show(Properties.Resources.SaveBeforNew, 
                                                    Properties.Resources.MsgBoxHeaderNew, 
                                                    MessageBoxButtons.YesNoCancel, 
                                                    MessageBoxIcon.Question);
                switch (rc)
                {
                    case DialogResult.Yes:
                        SaveFile(false);
                        NewRegExSet();
                        break;
                    case DialogResult.No:
                        NewRegExSet();
                        break;
                    case DialogResult.Cancel:
                        break;
                }
            }
            else
            {
                NewRegExSet();
            }
            
        }

        /// <summary>
        /// Öffnet eine vorhandene RegExSet Datei
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuFileOpenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (FileIsDirty)
            {
                DialogResult rc = MessageBox.Show(Properties.Resources.SaveBeforNew,
                                                    Properties.Resources.RegExStudio,
                                                    MessageBoxButtons.YesNoCancel,
                                                    MessageBoxIcon.Question);
                switch (rc)
                {
                    case DialogResult.Yes:
                        SaveFile(false);
                        LoadFile();
                        break;
                    case DialogResult.No:
                        LoadFile();
                        break;
                    case DialogResult.Cancel:
                        break;
                }
            }
            else
            {
                LoadFile();
            }

  
        }

        /// <summary>
        /// Speichert die Datei. Wenn es noch keine Datei gibt, wird ein Ort ausgewählt
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuFileSaveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFile(false);
            FileIsDirty = false;
        }

        /// <summary>
        /// Speichert die Datei an einem zu wählendem Ort
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuFileSaveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFile(true);
            FileIsDirty = false;
        }

        private void menuFilePrintToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void menuFilePrintCurrentRegExToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void menuFilePrintAllToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// RegEx Studio beenden
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuFileExitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close(); 
        }

        /// <summary>
        /// Die Schriftart des InputControls des aktuellen Tabs soll größer werden
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnIncreaseFont_Click(object sender, EventArgs e)
        {
            //Ermitteln in welchem Tab wir gerade sind
            CustomControls.CtrlRegExTab currentTab = tcRegExCollection.SelectedTab as CustomControls.CtrlRegExTab;

            if (currentTab != null)
            {
                currentTab.IncreaseFont();
            }
        }

        /// <summary>
        /// Die Schriftart des InputControls des aktuellen Tabs soll kleiner werden
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDecreaseFont_Click(object sender, EventArgs e)
        {
            //Ermitteln in welchem Tab wir gerade sind
            CustomControls.CtrlRegExTab currentTab = tcRegExCollection.SelectedTab as CustomControls.CtrlRegExTab;

            if (currentTab != null)
            {
                currentTab.DecreaseFont();
            }
        }

        /// <summary>
        /// Ruft im Browser die Webseite von RegExStudio auf Codeplex auf
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuHelpCodeplexToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("http://regexstudio.codeplex.com");
        }

        /// <summary>
        /// Zeige ein paar Infos über das Programm
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuHelpInfoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Dialogs.DialogInfo dlgInfo = new Dialogs.DialogInfo();
            dlgInfo.ShowDialog();
        }

        /// <summary>
        /// Verriegelung des Tab-Schliessen Buttons
        /// Er darf nur aktiv sein wenn mehr als ein Tab offen ist
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tcRegExCollection_ControlAdded(object sender, ControlEventArgs e)
        {
            if (tcRegExCollection.TabPages.Count > 1)
            {
                menuFileCloseToolStripMenuItem.Enabled = true;
                btnClose.Enabled = true;
            }
        }

        /// <summary>
        /// Verriegelung des Tab-Schliessen Buttons
        /// Er darf nur aktiv sein wenn mehr als ein Tab offen ist
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tcRegExCollection_ControlRemoved(object sender, ControlEventArgs e)
        {
            if (tcRegExCollection.TabPages.Count <= 2)
            {
                menuFileCloseToolStripMenuItem.Enabled = false;
                btnClose.Enabled = false;
            }
        }

        /// <summary>
        /// Bei einer Änderung an einer der RegEx die Datei als geändert markieren
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RegEx_Changed(object sender, RegExChangedEventArgs e)
        {
            FileIsDirty = true;
        }

        /// <summary>
        /// Das Formular/Programm wird geschlossen. Die übliche Frage ob gespeichert werden soll
        /// Wird das Programm über den TaskManager gekillt oder Windows heruntzergefahren wird nur gespeichert wenn es schon eine Datei gibt.
        /// Neue bearbeitete Sammlungen werden verworfen
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (FileIsDirty)
            {                
                switch (e.CloseReason)
                {
                    case CloseReason.UserClosing:
                    case CloseReason.ApplicationExitCall:
                        DialogResult rc = MessageBox.Show(Properties.Resources.SaveBeforExit,
                                                            Properties.Resources.MsgBoxHeaderExit, 
                                                            MessageBoxButtons.YesNoCancel, 
                                                            MessageBoxIcon.Question);
                        switch (rc)
                        {
                            case DialogResult.Yes:
                                break;
                            case DialogResult.No:
                                break;
                            case DialogResult.Cancel:
                                e.Cancel = true;
                                break;
                        }
                        break;

                    case CloseReason.WindowsShutDown:
                    case CloseReason.TaskManagerClosing:
                        if (_regExSet.FileName != string.Empty)
                        {
                            _regExSet.SaveToFile();
                        }
                        break;
                }
            }
        }

        /// <summary>
        /// Wählt eine Datei aus und öffnet sie dann
        /// </summary>
        private void LoadFile()
        {
            if (ofdRegEx.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                _controlMapping.Clear();
                _regExMapping.Clear();
                _regExSet = Xml.RegExSet.LoadFromFile(ofdRegEx.FileName);
                ShowRegExSet();
                FileIsDirty = false;
            }
        }

        /// <summary>
        /// Speichert das RegExSet. 
        /// </summary>
        /// <param name="saveAs"></param>
        private void SaveFile(bool saveAs)
        {
            if (_regExSet.FileName == string.Empty || saveAs)
            {
                if (sfdRegEx.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    _regExSet.SaveToFile(sfdRegEx.FileName);
                    lblFileName.Text = sfdRegEx.FileName;
                }
            }
            else
            {
                _regExSet.SaveToFile();
            }
        
        }

        /// <summary>
        /// Erstellt ein neues RegEx Set
        /// </summary>
        private void NewRegExSet()
        {
            _controlMapping.Clear();
            _regExMapping.Clear();
            tcRegExCollection.TabPages.Clear();
            _regExSet = new Xml.RegExSet();
            _regExSet.InitRegExSet();
            ShowRegExSet();
            lblFileName.Text = Properties.Resources.DefaultFileName;
            FileIsDirty = false;
        }

        /// <summary>
        /// Zeigt ein RegExSet an
        /// (Erzeugt die Tabs)
        /// </summary>
        private void ShowRegExSet()
        {
            _controlMapping.Clear();
            _regExMapping.Clear();
            tcRegExCollection.TabPages.Clear();
            foreach (Xml.RegExSetRegEx regEx in _regExSet.Items)
            {
                AddRegExTab(regEx);
            }
            if (_regExSet.FileName == string.Empty)
            {
                lblFileName.Text = Properties.Resources.DefaultFileName;
            }
            else
            {
                lblFileName.Text = _regExSet.FileName;
            }
        }

        /// <summary>
        /// Erstellt eine neue RegEx und fügt sie den Tabs hinzu
        /// </summary>
        private void NewRegEx()
        {
            Xml.RegExSetRegEx regEx = new Xml.RegExSetRegEx();
            _regExCount++;
            regEx.Name = string.Format("{0} - {1}", Properties.Resources.DefaultRegExName, _regExCount);
            _regExSet.AddItem(regEx);
            AddRegExTab(regEx);
        }

        /// <summary>
        /// Fügt für eine RegEx ein neues Tab hinzu
        /// </summary>
        /// <param name="regEx"></param>
        private void AddRegExTab(Xml.RegExSetRegEx regEx)
        {
            CustomControls.CtrlRegExTab tab = new CustomControls.CtrlRegExTab(regEx);
            tab.RegExChanged += new CustomControls.CtrlRegExTab.RegExChangedEventHandler(RegEx_Changed);

            tcRegExCollection.TabPages.Add(tab);

            _controlMapping.Add(tab, regEx);
            _regExMapping.Add(regEx, tab);
        }

        /// <summary>
        /// Schliesst ein Tab und entfernt die dazugehörende RegEx aus dem RegEx Set
        /// </summary>
        /// <param name="tab">Das zu schliessende Tab</param>
        private void CloseTab(CustomControls.CtrlRegExTab tab)
        {
            Xml.RegExSetRegEx regEx = _controlMapping[tab];
            _regExSet.RemoveItem(regEx);
            _controlMapping.Remove(tab);
            _regExMapping.Remove(regEx);
            tcRegExCollection.TabPages.Remove(tab);
            tab.Dispose();
            tab = null;
        }

    }
}
